home *** CD-ROM | disk | FTP | other *** search
- UNIT AnsiCrt;
- { Ian Hinson using Turbo Pascal 6.0
- 3:633/357 18 March 1993 }
- { This Unit contains most functions & procedures in common use in the
- CRT Unit. To that extent it is intended as a replacement to the CRT unit
- and should not be used at the same time.
- See the INTERFACE section for a list of constants, variables, functions
- and procedures provided by this unit.
-
- DosCrt differs from the CRT Unit in that DOS is used for input and output.
- This provides the following advantages:
- 1. Output can be redirected using DOS redirection
- 2. The routines should work on any 80x86 based machine using compatible
- DOS (although non-IBMPC architectures have long since been driven from
- consideration through programmers writing to the hardware environment
- instead of the operating system.)
- 3. The use of DOS standard input/output and ANSI means that programs that
- use this unit may feasibly be operated via a remote ANSI terminal.
-
- This unit has been adapted from the unit ANSCRT.PAS by Rick Housh.
- However, a new approach used to implement most procedures (see below)
- means the code is practically all new, except for the simplest procedures.
- e.g. ClrScr, ClrEol, and most cursor functions.
-
- I have reworked the TextColor procedure by using a Decision Tree
- implementation technique instead of conventional structured logic
- programming; With the desired result that:
- 1) there is now only ONE Ansi sequence written to the output device
- for each invocation of TextColor.
- 2) those sequences contain no redundancy e.g. (no) turning on bold when it
- was already on, or (no) resetting all attributes when all that is needed
- is to ADD an attribute.
- The original ANSCrt Unit used a 'broad-brush' approach which simplified
- the logic but caused redundancy of Ansi sequences.
-
- Ansi detection has been made into a separate user-available function.
-
- I have rewritten Keypressed and ReadKey. I don't believe that the speed
- required for these routines is so great that ASM or INLINE code is
- warranted, so I opted for the clearer DOS Unit 'Registers' method.
-
- User variables CheckEOF and TextAttr were abolished since they weren't
- fully implemented anyway. }
-
-
- INTERFACE
-
- CONST
- Black = 0; Blue = 1; Green = 2; Cyan = 3;
- Red = 4; Magenta = 5; Brown = 6; LightGray = 7;
- DarkGray = 8; LightBlue = 9; LightGreen = 10; LightCyan = 11;
- LightRed = 12; LightMagenta = 13; Yellow = 14; White = 15;
- Blink = 128;
-
- VAR CheckBreak: BOOLEAN;
-
- FUNCTION KeyPressed : BOOLEAN;
- FUNCTION ReadKey : CHAR;
- FUNCTION AnsiDetected: BOOLEAN; { new to this unit }
- PROCEDURE TextColor(fore : Byte);
- PROCEDURE TextBackGround(back : BYTE);
- PROCEDURE NormVideo;
- PROCEDURE LowVideo;
- PROCEDURE HighVideo;
- PROCEDURE ClrEol;
- PROCEDURE ClrScr;
- PROCEDURE WhereXY(VAR x,y: BYTE); { new to this unit }
- FUNCTION WhereX: BYTE;
- FUNCTION WhereY: BYTE;
- PROCEDURE GotoXY(x,y: BYTE);
-
- IMPLEMENTATION
- USES Dos;
-
- CONST forestr: ARRAY[Black..LightGray] OF STRING[2]
- = ('30','34','32','36','31','35','33','37');
- backstr: ARRAY[Black..LightGray] OF STRING[2]
- = ('40','44','42','46','41','45','43','47');
- decisiontree: ARRAY[BOOLEAN, BOOLEAN, BOOLEAN, BOOLEAN] OF INTEGER =
- ((((0,1),(2,0)),((1,1),(3,3))),(((4,5),(6,4)),((0,5),(2,0))));
-
- VAR forecolour, backcolour: BYTE; { stores last colours set }
- boldstate, blinkstate: BOOLEAN;
-
- FUNCTION KeyPressed : BOOLEAN;
- { Detects whether a key is pressed. Key remains in kbd buffer}
- VAR r: REGISTERS;
- BEGIN
- r.AH := $0B;
- MsDos(r);
- Keypressed := (r.AL = $FF)
- END;
-
- FUNCTION ReadKey : CHAR;
- { Will wait for key }
- VAR r: REGISTERS;
- BEGIN
- r.AH := $07;
- MsDos(r);
- IF CheckBreak AND (r.AL = $03) THEN Intr($23,r);
- ReadKey := Chr(r.AL)
- END;
-
- FUNCTION AnsiDetected: BOOLEAN;
- { Detects whether ANSI is installed. }
- VAR dummy: CHAR;
- BEGIN Write(#27'[6n'); { Ask for cursor position report via }
- IF NOT keypressed { the ANSI driver. }
- THEN AnsiDetected := FALSE
- ELSE BEGIN
- AnsiDetected := TRUE;
- { empty the keyboard buffer }
- REPEAT Dummy := Readkey UNTIL NOT Keypressed
- END
- END;
-
- PROCEDURE TextColor(fore : Byte);
- VAR
- blinknow, boldnow: BOOLEAN;
- outstr: STRING;
- BEGIN
- blinknow := (fore AND $80) = $80;
- boldnow := (fore AND $08) = $08;
- fore := fore AND $07; { mask out intensity and blink attributes }
- forecolour := fore;
- CASE decisiontree[blinknow, blinkstate, boldnow, boldstate] OF
- 0: outstr := Concat(#27,'[',forestr[fore],'m');
- 1: outstr := Concat(#27,'[0;',backstr[backcolour],';',forestr[fore],'m');
- 2: outstr := Concat(#27,'[1;',forestr[fore],'m');
- 3: outstr := Concat(#27,'[0;1;',backstr[backcolour],';',forestr[fore],'m');
- 4: outstr := Concat(#27,'[5;',forestr[fore],'m');
- 5: outstr := Concat(#27,'[0;5;',backstr[backcolour],';',forestr[fore],'m');
- 6: outstr := Concat(#27,'[1;5;',forestr[fore],'m');
- END; { CASE }
- Write(outstr);
- blinkstate := blinknow;
- boldstate := boldnow;
- END;
-
- PROCEDURE TextBackGround(back: BYTE);
- VAR outstring: STRING;
- BEGIN
- IF Back > 7 THEN Exit; { No such thing as bright or blinking backgrounds }
- BackColour := Back;
- outstring := Concat(#27,'[',backstr[back],'m');
- Write(outstring)
- END;
-
- PROCEDURE NormVideo;
- BEGIN
- Write(#27'[0m');
- forecolour := LightGray;
- backcolour := Black;
- boldstate := FALSE;
- blinkstate := FALSE
- END;
-
- PROCEDURE LowVideo;
- BEGIN
- IF blinkstate THEN forecolour := forecolour OR $80; { retain blinking }
- TextColor(forecolour); { stored forecolour never contains bold attr }
- END;
-
- PROCEDURE HighVideo;
- BEGIN
- IF NOT boldstate THEN
- BEGIN
- boldstate := TRUE;
- Write(#27,'[1m')
- END;
- END;
-
- PROCEDURE ClrEol;
- BEGIN
- Write(#27'[K')
- END;
-
- PROCEDURE ClrScr;
- BEGIN
- Write(#27'[2J');
- END;
-
- PROCEDURE WhereXY(VAR x,y: BYTE);
- VAR
- ch : char;
- st : String;
- st1: String[2];
- i : integer;
- BEGIN
- Write(#27'[6n'); { Ansi string to get X-Y position }
- st := '';
- REPEAT
- ch := readkey; { Get one }
- st := st + ch; { Build string }
- UNTIL ch = 'R';
- WHILE Keypressed DO ch := ReadKey; {clear kbd buffer}
- St1 := copy(St,6,2); { Pick off substring having number in ASCII}
- Val(St1,x,i); { Make it numeric }
- St1 := copy(St,3,2); { Pick off substring having number in ASCII}
- Val(St1,y,i); { Make it numeric }
- END;
-
- FUNCTION WhereX: BYTE;
- VAR x,y: BYTE;
- BEGIN
- WhereXY(x,y);
- WhereX := x
- END;
-
- FUNCTION WhereY: BYTE;
- VAR x,y: BYTE;
- BEGIN
- WhereXY(x,y);
- WhereY := y
- END;
-
- PROCEDURE GotoXY(x,y: BYTE);
- BEGIN
- IF (x < 1) OR (y < 1) THEN Exit;
- IF (x > 80) OR (y > 25) THEN Exit;
- Write(#27'[',y,';',x,'H');
- END;
-
- BEGIN
- CheckBreak := TRUE;
- forecolour := LightGray;
- backcolour := Black;
- boldstate := FALSE;
- blinkstate := FALSE
- END.
-